package com.tundriki.pref;

import java.nio.FloatBuffer;

import android.util.FloatMath;

public class GeomSolver {
	
	public static float[] getArray(FloatBuffer buf) {
		float[] rv = new float[buf.limit()];
		buf.position(0);
		for(int i=0; i < rv.length; i ++)
			rv[i] = buf.get();
		return rv;
	}
	
	public static float[] normal(FloatBuffer vertices) {
		return normal(getArray(vertices));
	}
	
	public static float vectLen(float[] v) {
		return FloatMath.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
	}
	
	public static float[] normal(float[] vertices) {
		float[] rv = new float[4],
				a = new float[3],
				b = new float[3];
		float len = 0;
		
		a[0] = vertices[0]-vertices[3];
		a[1] = vertices[1]-vertices[4];
		a[2] = vertices[2]-vertices[5];
		
		b[0] = vertices[6]-vertices[3];
		b[1] = vertices[7]-vertices[4];
		b[2] = vertices[8]-vertices[5];
		
		rv[0] = a[1]*b[2] - a[2]*b[1];
		rv[1] = a[2]*b[0] - a[0]*b[2];
		rv[2] = a[0]*b[1] - a[1]*b[0];
		
		len = vectLen(rv);
		
		if (len>0) {
			rv[0] /= len;
			rv[1] /= len;
			rv[2] /= len;
		}
		
		rv[3] = -rv[0]*vertices[3]-rv[1]*vertices[4]-rv[2]*vertices[5];
		
		return rv;
	}
	
	public static float vectAngleCos(float[] v1, float[] v2) {
		float ll = vectLen(v1)*vectLen(v2),
			prod = v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2];
		
		return (ll==0)?-2:(prod / ll);
	}
	
	public static float[] lineParams(float[][] lineCoord) {
		float[] rv = new float[5];
		float dx = lineCoord[1][0]-lineCoord[0][0],
			dy =  lineCoord[1][1]-lineCoord[0][1],
			dz =  lineCoord[1][2]-lineCoord[0][2];
		if (dz==0)
			return null;
		rv[0] = lineCoord[0][0];
		rv[1] = lineCoord[0][1];
		rv[2] = lineCoord[0][2];
		rv[3] = dx/dz;
		rv[4] = dy/dz;
		return rv;
	}
	
	public static float[] planeIntersection(float[] norm, float[][] line) {
		float[] rv = new float[3],
				ln = lineParams(line);
		float pr,dv;
		if (ln==null)
			return null;
		dv = norm[0]*ln[3] + norm[1]*ln[4] + norm[2];
		if (dv==0)
			return null;
		pr = norm[0]*ln[3]*ln[2] + norm[1]*ln[4]*ln[2] - norm[0]*ln[0] - norm[1]*ln[1] - norm[3];
		
		rv[2] = pr/dv;
		rv[0] = ln[0] + ln[3]*(rv[2]-ln[2]);
		rv[1] = ln[1] + ln[4]*(rv[2]-ln[2]);
		
		return rv;
	}
	
	public static float[][] copyVertices(FloatBuffer buf, int[] order) {
		float[][]  rv = new float[order.length][3];
		
		for(int i=0;i<order.length;i++) {
			buf.position(order[i]*3);
			rv[i][0] = buf.get();
			rv[i][1] = buf.get();
			rv[i][2] = buf.get();
		}
		return rv;
	}

	public static boolean pointInsidePolygon(FloatBuffer buf, int[] vertOrder, float[] point) {
		float angle = 0;
		float[] v1 = {0,0,0}, //vector between intersection point and current vertex
				v2 = {0,0,0}; //vector between current vertex and next vertex
		float[][] v = copyVertices(buf, vertOrder);
		
		for(int i=0;i<vertOrder.length;i++) {
			int j = (i + 1) % vertOrder.length;
			for (int k=0; k<3; k++) {
				v1[k] = point[k] - v[i][k];
				v2[k] = v[j][k] - v[i][k];
			}
			angle += Math.acos(GeomSolver.vectAngleCos(v1, v2));
		}
		return Math.abs(Math.PI*2 - angle)<0.001;
	}

	

}
